import { hexToRgb, colorDistance, limitColorDepth, applyPalette, PRESET_PALETTES } from '../pixelator';

describe('像素化工具函数', () => {
  describe('hexToRgb', () => {
    test('应该正确转换十六进制颜色到RGB', () => {
      expect(hexToRgb('#ff0000')).toEqual({ r: 255, g: 0, b: 0 });
      expect(hexToRgb('#00ff00')).toEqual({ r: 0, g: 255, b: 0 });
      expect(hexToRgb('#0000ff')).toEqual({ r: 0, g: 0, b: 255 });
      expect(hexToRgb('#ffffff')).toEqual({ r: 255, g: 255, b: 255 });
      expect(hexToRgb('#000000')).toEqual({ r: 0, g: 0, b: 0 });
    });

    test('应该处理不带#前缀的十六进制颜色', () => {
      expect(hexToRgb('ff0000')).toEqual({ r: 255, g: 0, b: 0 });
      expect(hexToRgb('00ff00')).toEqual({ r: 0, g: 255, b: 0 });
    });

    test('应该返回null对于无效的十六进制颜色', () => {
      expect(hexToRgb('invalid')).toBeNull();
      expect(hexToRgb('#zzzzzz')).toBeNull();
      expect(hexToRgb('#ff00')).toBeNull();
      expect(hexToRgb('#ff00000')).toBeNull();
    });
  });

  describe('colorDistance', () => {
    test('应该正确计算颜色距离', () => {
      // 相同颜色距离为0
      expect(colorDistance({ r: 255, g: 0, b: 0 }, { r: 255, g: 0, b: 0 })).toBe(0);

      // 红色到绿色的距离
      expect(colorDistance({ r: 255, g: 0, b: 0 }, { r: 0, g: 255, b: 0 })).toBeCloseTo(360.624, 1);

      // 黑色到白色的距离
      expect(colorDistance({ r: 0, g: 0, b: 0 }, { r: 255, g: 255, b: 255 })).toBeCloseTo(441.672, 1);
    });

    test('应该处理边界情况', () => {
      expect(colorDistance({ r: 0, g: 0, b: 0 }, { r: 1, g: 1, b: 1 })).toBeCloseTo(1.732, 3);
      expect(colorDistance({ r: 255, g: 255, b: 255 }, { r: 254, g: 254, b: 254 })).toBeCloseTo(1.732, 3);
    });
  });

  describe('limitColorDepth', () => {
    test('应该正确限制颜色深度', () => {
      // 1-bit颜色深度 (2色)
      expect(limitColorDepth({ r: 127, g: 127, b: 127 }, 1)).toEqual({ r: 128, g: 128, b: 128, a: 255 });
      expect(limitColorDepth({ r: 126, g: 126, b: 126 }, 1)).toEqual({ r: 128, g: 128, b: 128, a: 255 });

      // 2-bit颜色深度 (4色)
      expect(limitColorDepth({ r: 63, g: 63, b: 63 }, 2)).toEqual({ r: 64, g: 64, b: 64, a: 255 });
      expect(limitColorDepth({ r: 191, g: 191, b: 191 }, 2)).toEqual({ r: 192, g: 192, b: 192, a: 255 });

      // 8-bit颜色深度 (256色) - 应该保持不变
      expect(limitColorDepth({ r: 123, g: 45, b: 67 }, 8)).toEqual({ r: 123, g: 45, b: 67, a: 255 });
    });

    test('应该处理边界值', () => {
      expect(limitColorDepth({ r: 0, g: 0, b: 0 }, 1)).toEqual({ r: 0, g: 0, b: 0, a: 255 });
      expect(limitColorDepth({ r: 255, g: 255, b: 255 }, 1)).toEqual({ r: 255, g: 255, b: 255, a: 255 });
    });
  });

  describe('applyPalette', () => {
    const testPalette = ['#ff0000', '#00ff00', '#0000ff', '#ffffff', '#000000'];

    test('应该选择最接近的调色板颜色', () => {
      // 接近红色
      expect(applyPalette({ r: 250, g: 10, b: 10 }, testPalette)).toEqual({ r: 255, g: 0, b: 0, a: 255 });

      // 接近绿色
      expect(applyPalette({ r: 10, g: 250, b: 10 }, testPalette)).toEqual({ r: 0, g: 255, b: 0, a: 255 });

      // 接近蓝色
      expect(applyPalette({ r: 10, g: 10, b: 250 }, testPalette)).toEqual({ r: 0, g: 0, b: 255, a: 255 });
    });

    test('应该处理预设调色板', () => {
      const gameboyPalette = PRESET_PALETTES.find(p => p.name === 'Game Boy')?.colors;
      if (!gameboyPalette) throw new Error('Game Boy palette not found');

      // 测试Game Boy调色板
      expect(applyPalette({ r: 20, g: 60, b: 20 }, gameboyPalette)).toEqual({ r: 15, g: 56, b: 15, a: 255 });
      expect(applyPalette({ r: 150, g: 180, b: 20 }, gameboyPalette)).toEqual({ r: 155, g: 188, b: 15, a: 255 });
    });

    test('应该处理空调色板', () => {
      expect(applyPalette({ r: 100, g: 100, b: 100 }, [])).toEqual({ r: 100, g: 100, b: 100, a: 255 });
    });
  });

  describe('PRESET_PALETTES', () => {
    test('应该包含预设的调色板', () => {
      expect(PRESET_PALETTES).toHaveLength(4);
      expect(PRESET_PALETTES.map(p => p.name)).toEqual([
        'Game Boy',
        'NES',
        'CGA',
        'Mono (1-bit)'
      ]);
    });

    test('每个调色板应该有正确的颜色数量', () => {
      expect(PRESET_PALETTES[0].colors).toHaveLength(4); // Game Boy
      expect(PRESET_PALETTES[1].colors).toHaveLength(8); // NES
      expect(PRESET_PALETTES[2].colors).toHaveLength(8); // CGA
      expect(PRESET_PALETTES[3].colors).toHaveLength(2); // Mono
    });
  });
});
